#include <iostream>
#include <array>
#include <tuple>
#include <string>
#include <sstream>

#include <iostream>
using namespace std;

/*
traits，又被叫做特性萃取技术，说得简单点就是提取“被传进的对象”对应的返回类型，让同一个接口实现对应的功能。
算法的实现并不知道自己被传进来什么。

本文演示如何获取返回类型，
但没有解析传入参数。


*/
namespace TraitsLearn3 {



    /*先定义一些tag*/
    struct A {
        float a;
    };
    struct B : A {
        float b;
    }; // 继承的好处就是，当函数需要参数为A，
                    // 而你传入的参数为B的时候，可以往上一直找到适合的对象

    /*假设有一个未知类*/
    template <class AorB>
    struct unknown_class{
        typedef AorB return_type;
    };

    /*特性萃取器  获取到返回类型*/
    template <class unknown_class>
    struct unknown_class_traits {
        typedef typename unknown_class::return_type return_type;
    };

    /*特性萃取器 —— 针对原生指针*/
    template <class T>
    struct unknown_class_traits<T*> {
        typedef T return_type;
    };

    /*特性萃取其 —— 针对指向常数*/
    template <class T>
    struct unknown_class_traits<const T*> {
        typedef const T return_type;
    };


    /*决定使用哪一个类型*/
    template <class unknown_class>
    inline typename unknown_class_traits<unknown_class>::return_type
        return_type(unknown_class) {
        typedef typename unknown_class_traits<unknown_class>::return_type RT;
        return RT();
    }

    template <class unknown_class>
    inline typename unknown_class_traits<unknown_class>::return_type
        __func(unknown_class u, A) {
        A a;
        a.a = 10;
        cout << "use A flag" << endl;
     //   return A();
        return a;
    }

    template <class unknown_class>
    inline typename unknown_class_traits<unknown_class>::return_type
        __func(unknown_class, B) {
        cout << "use B flag" << endl;
        return B();
    }

    template <class unknown_class, class T>
    T __func(unknown_class, T) {
        cout << "use origin ptr" << endl;
        return T();
    }

    template <class unknown_class>
    inline typename unknown_class_traits<unknown_class>::return_type
        func(unknown_class u) {
        typedef typename unknown_class_traits<unknown_class>::return_type return_type;
        return __func(u, return_type());
    }

    int main() {
        unknown_class<B> b;//无意义，无法赋值
        unknown_class<A> a;//无意义，无法赋值
        unknown_class<int> x;//无意义，无法赋值
        unknown_class<float> y;//无意义，无法赋值
        int value = 1;
        int* p = &value;

        float f = 1;
        float* pFloat = &f;


        A v1 = func(a);
        cout << " v1.a=" << v1.a << endl;
       
        B v2 = func(b);
        int v3 = func(p);
    //    int v4 = func(value);
        float v4 = func(pFloat);
        
        int v5 = func(x);
        float v6 = func(y);

        return 0;
    }
   
}
